package com.strelitzia.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mysql.cj.util.StringUtils;
import com.strelitzia.dao.ReviewDao;
import com.strelitzia.entity.*;
import com.strelitzia.exception.StrelitziaException;
import com.strelitzia.filter.CorsFilter;
import com.strelitzia.service.*;
import com.strelitzia.utils.TimeUtil;
import com.strelitzia.vo.RecoverVo;
import com.strelitzia.vo.ReviewItem;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @create 2023/12/26 16:14
 */
@Service
public class ReviewServiceImpl extends ServiceImpl<ReviewDao, ReviewEntity> implements ReviewService {
    @Autowired
    UserService userService;
    @Autowired
    FriendsService friendsService;
    @Autowired
    NotificationService notificationService;

    @Autowired
    DynamicService dynamicService;

    @Override
    public List<ReviewItem> getTop3ForTime(Integer did) {
        Integer id = CorsFilter.loginUserId.get();
        List<ReviewEntity> list = this.list(new QueryWrapper<ReviewEntity>()
                .eq("review_id", did)
                .eq("type", 1)
                .orderByDesc("review_time")
                .last("limit 3"));
        return getReviewItems(id, list);
    }

    private List<ReviewItem> getReviewItems(Integer id, List<ReviewEntity> list) {
        if (list != null) {
            return list.stream().map(item -> {
                ReviewItem reviewItem = new ReviewItem();
                BeanUtils.copyProperties(item, reviewItem);
                UserEntity byId = userService.getById(item.getUid());
                reviewItem.setIsLiked(item.getLikeIds().contains("[" + id.toString() + "]"));
                reviewItem.setAvatar("/api/res/" + byId.getAvatar());
                reviewItem.setHaveReview(this.count(new QueryWrapper<ReviewEntity>().eq("review_id", item.getId()).ne("type", 1)) >= 1);
                FriendsEntity one = friendsService.getOne(new QueryWrapper<FriendsEntity>().eq("uid", id).eq("friend_id", item.getUid()));
                reviewItem.setNickname(byId.getNickname());
                if (one != null) {
                    if (!StringUtils.isNullOrEmpty(one.getRemark())) {
                        reviewItem.setNickname(one.getRemark());
                    }
                }
                reviewItem.setTime(TimeUtil.formattingTime(item.getReviewTime()));
                return reviewItem;
            }).collect(Collectors.toList());
        }
        return null;
    }

    @Override
    public List<ReviewItem> getTop3ForHot(Integer did) {
        Integer id = CorsFilter.loginUserId.get();

        List<ReviewEntity> list = this.list(new QueryWrapper<ReviewEntity>()
                .eq("review_id", did)
                .eq("type", 1)
                .orderByDesc("likes")
                .orderByDesc("review_time")
                .last("limit 3"));
        return getReviewItems(id, list);
    }

    @Override
    public List<ReviewItem> getAllForTime(Integer did) {
        Integer id = CorsFilter.loginUserId.get();
        List<ReviewEntity> list = this.list(new QueryWrapper<ReviewEntity>()
                .eq("review_id", did)
                .eq("type", 1)
                .orderByDesc("review_time"));
        return getReviewItems(id, list);
    }

    @Override
    public List<ReviewItem> getAllForHot(Integer did) {
        Integer id = CorsFilter.loginUserId.get();
        List<ReviewEntity> list = this.list(new QueryWrapper<ReviewEntity>()
                .eq("review_id", did)
                .eq("type", 1)
                .orderByDesc("likes")
                .orderByDesc("review_time"));
        return getReviewItems(id, list);
    }

    @Override
    public void like(Integer id) throws StrelitziaException {
        ReviewEntity reviewEntity = this.getById(id);
        if (reviewEntity != null) {
            reviewEntity.setLikes(reviewEntity.getLikes() + 1);
            reviewEntity.setLikeIds(reviewEntity.getLikeIds() + "[" + CorsFilter.loginUserId.get() + "]");
            NotificationEntity notificationEntity = new NotificationEntity();
            notificationEntity.setAppend(id);
            notificationEntity.setMessage("点赞了你的评论");
            notificationEntity.setNotifier(CorsFilter.loginUserId.get());
            notificationEntity.setReceiver(reviewEntity.getUid());
            notificationEntity.setType(1);
            notificationEntity.setTime(new Timestamp(new Date().getTime()));
            if (!notificationEntity.getReceiver().equals(notificationEntity.getNotifier())) {
                this.notificationService.save(notificationEntity);
            }
            this.updateById(reviewEntity);
        } else {
            throw new StrelitziaException("评论不存在");
        }
    }

    @Override
    public void unlike(Integer id) throws StrelitziaException {
        ReviewEntity reviewEntity = this.getById(id);
        if (reviewEntity != null) {
            reviewEntity.setLikes(reviewEntity.getLikes() - 1);
            reviewEntity.setLikeIds(reviewEntity.getLikeIds().replace("[" + CorsFilter.loginUserId.get() + "]", ""));
            this.updateById(reviewEntity);
        } else {
            throw new StrelitziaException("评论不存在");

        }
    }

    @Override
    public void del(Integer id) {
        ReviewEntity byId = this.getById(id);
        if (byId.getType() == 2) {
            this.remove(new QueryWrapper<ReviewEntity>().eq("type", 3).eq("recover_id", id));
        } else if (byId.getType() == 1) {
            List<ReviewEntity> list = this.list(new QueryWrapper<ReviewEntity>().eq("type", 2).eq("review_id", id));
            if (list != null) {
                for (ReviewEntity reviewEntity : list) {
                    this.remove(new QueryWrapper<ReviewEntity>().eq("type", 3).eq("recover_id", reviewEntity.getId()));
                    this.removeById(reviewEntity.getId());
                }
            }
        }
        this.removeById(id);

    }

    @Override
    public void recover(Integer id, String context) throws StrelitziaException {
        ReviewEntity reviewEntity = this.getById(id);
        ReviewEntity recover = new ReviewEntity();
        if (reviewEntity != null) {
            recover.setContent(context);
            recover.setUid(CorsFilter.loginUserId.get());
            recover.setReviewTime(new Timestamp(new Date().getTime()));
            recover.setReviewId(id);
            recover.setLikes(0);
            recover.setLikeIds("");
            NotificationEntity notificationEntity = new NotificationEntity();
            notificationEntity.setNotifier(CorsFilter.loginUserId.get());
            notificationEntity.setReceiver(reviewEntity.getUid());
            notificationEntity.setType(1);
            notificationEntity.setMessage("回复了你的评论：" + context);
            if (reviewEntity.getType() == 1) {
//                DynamicEntity byId = dynamicService.getById(reviewEntity.getReviewId());
//                if (!byId.getUid().equals(CorsFilter.loginUserId.get())) {
//                    notificationEntity.setMessage("评论：" + context);
//                }
                recover.setType(2);
            } else {
                recover.setType(3);
                recover.setRecoverId(reviewEntity.getRecoverId());
            }

            this.save(recover);

            if (recover.getType() == 2) {
                recover.setRecoverId(recover.getId());
                this.updateById(recover);
            }

            notificationEntity.setAppend(recover.getReviewId());
            notificationEntity.setTime(recover.getReviewTime());
            if (!notificationEntity.getReceiver().equals(notificationEntity.getNotifier())) {
                this.notificationService.save(notificationEntity);
            }
        }else {
            throw new StrelitziaException("该评论已删除");
        }
    }

    @Override
    public List<RecoverVo> reviewsForHot(Integer id) {
        List<ReviewEntity> list = this.list(new QueryWrapper<ReviewEntity>()
                .eq("review_id", id)
                .eq("type", 2)
                .orderByDesc("likes")
                .orderByDesc("review_time"));
        return getRecovers(list);
    }

    private List<RecoverVo> getRecovers(List<ReviewEntity> list) {
        if (list != null) {
            return list.stream().map(item -> {
                RecoverVo recoverVo = new RecoverVo();
                Recover recover = new Recover();
                BeanUtils.copyProperties(item, recover);
                UserEntity byId = userService.getById(item.getUid());
                recover.setIsLiked(item.getLikeIds().contains("[" + CorsFilter.loginUserId.get().toString() + "]"));
                recover.setNickname(byId.getNickname());
                recover.setTime(TimeUtil.formattingTime(item.getReviewTime()));
                recoverVo.setRecover(recover);
                List<ReviewEntity> entityList = this.list(new QueryWrapper<ReviewEntity>()
                        .eq("recover_id", item.getId())
                        .eq("type", 3)
                        .orderByDesc("review_time"));
                if (entityList != null) {
                    recoverVo.setRecovers(entityList.stream().map(i_item -> {
                        Recover recover2 = new Recover();
                        BeanUtils.copyProperties(i_item, recover2);
                        UserEntity byId2 = userService.getById(i_item.getUid());
                        recover2.setIsLiked(i_item.getLikeIds().contains("[" + CorsFilter.loginUserId.get().toString() + "]"));
                        recover2.setNickname(byId2.getNickname());
                        ReviewEntity reviewEntity = this.getById(i_item.getReviewId());
                        UserEntity userEntity = userService.getById(reviewEntity.getUid());
                        recover2.setReviewName(userEntity.getNickname());
                        recover2.setTime(TimeUtil.formattingTime(i_item.getReviewTime()));
                        return recover2;
                    }).collect(Collectors.toList()));
                }
                return recoverVo;
            }).collect(Collectors.toList());
        } else {
            return null;
        }
    }

    @Override
    public List<RecoverVo> reviewsForTime(Integer id) {
        List<ReviewEntity> list = this.list(new QueryWrapper<ReviewEntity>()
                .eq("review_id", id)
                .eq("type", 2).
                orderByDesc("review_time"));
        return getRecovers(list);
    }

    @Transactional
    @Override
    public void review(Integer did, String content) throws StrelitziaException {
        ReviewEntity reviewEntity = new ReviewEntity();
        DynamicEntity byId1 = dynamicService.getById(did);
        if(byId1 != null) {
            reviewEntity.setUid(CorsFilter.loginUserId.get());
            reviewEntity.setContent(content);
            reviewEntity.setType(1);
            reviewEntity.setReviewId(did);
            reviewEntity.setReviewTime(new Timestamp(new Date().getTime()));
            reviewEntity.setLikes(0);
            reviewEntity.setLikeIds("");
            this.save(reviewEntity);
            NotificationEntity notificationEntity = new NotificationEntity();
            notificationEntity.setAppend(did);
            notificationEntity.setMessage("评论了你的动态：" + reviewEntity.getContent());
            notificationEntity.setNotifier(CorsFilter.loginUserId.get());
            notificationEntity.setReceiver(byId1.getUid());
            notificationEntity.setType(0);
            notificationEntity.setTime(reviewEntity.getReviewTime());
            if (!notificationEntity.getReceiver().equals(notificationEntity.getNotifier())) {
                this.notificationService.save(notificationEntity);
            }
        } else {
            throw new StrelitziaException("评论失败, 该动态已删除");
        }

    }
}
